package com.wsx.ones.boots.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.*;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author wangshuaixin
 * @Title: com.wsx.sky.http.service.HttpClientUtils
 * @Description: TODO
 * @date 2018/12/10
 */
public class HttpClientUtils {


    private static PoolingHttpClientConnectionManager clientConnectionManager = null;
    private static RequestConfig requestConfig = null;

    protected static CloseableHttpClient httpClient = null;

    private static final int RETRY = 2;

    static {
        clientConnectionManager = new PoolingHttpClientConnectionManager();
        clientConnectionManager.setMaxTotal(500);
        clientConnectionManager.setDefaultMaxPerRoute(100);
    }

    protected static HttpRequestRetryHandler getRetryHandler() {
        HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception,
                                        int executionCount, HttpContext context) {
                if (executionCount >= RETRY) {// 如果已经重试了n次，就放弃
                    return false;
                }
                if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接，那么就重试
                    return true;
                }
                if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
                    return false;
                }
                if (exception instanceof InterruptedIOException) {// 超时
                    return false;
                }
                if (exception instanceof UnknownHostException) {// 目标服务器不可达
                    return false;
                }
                if (exception instanceof ConnectTimeoutException) {// 连接被拒绝
                    return false;
                }
                if (exception instanceof SSLException) {// SSL握手异常
                    return false;
                }

                HttpClientContext clientContext = HttpClientContext.adapt(context);
                HttpRequest request = clientContext.getRequest();
                // 如果请求是幂等的，就再次尝试
                if (!(request instanceof HttpEntityEnclosingRequest)) {
                    return true;
                }
                return false;
            }
        };
        return httpRequestRetryHandler;
    }

    public static CloseableHttpClient getHttpClient() {
        if (null == requestConfig) {
            requestConfig = RequestConfig.custom()
                    .setConnectTimeout(1000)//连接超时
                    .setSocketTimeout(2000)//读取超时
                    .setConnectionRequestTimeout(500)//从连接池中获得连接的超时
                    .build();
        }
        if (null == httpClient) {
            httpClient = HttpClientBuilder.create()
                    .setConnectionManager(clientConnectionManager)
                    .setRetryHandler(getRetryHandler())
                    //长连接需要显示在header上增加keep-alive
                    .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
                    .setDefaultRequestConfig(requestConfig).build();
        }
        return httpClient;
    }

    public static String get(String url, String code) throws Exception {
        if (null == code) {
            code = "UTF-8";
        }
        HttpGet httpGet = new HttpGet(url);

        httpGet.setHeader("Content-type", "application/json; charset=" + code);
        CloseableHttpResponse response = null;
        String rtn = "";
        InputStream in = null;
        BufferedReader reader = null;

        try {
            response = getHttpClient().execute(httpGet);

            HttpEntity httpEntity = response.getEntity();
            in = httpEntity.getContent();
            reader = new BufferedReader(new InputStreamReader(in, code));
            StringBuffer sb = new StringBuffer();

            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            rtn = sb.toString();
            return rtn;
        } catch (Exception e) {
            throw e;
        } finally {
            if (null != reader) {
                try {
                    reader.close();
                } catch (Exception e) {

                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (Exception e) {

                }
            }
            if (null != response) {
                try {
                    response.close();
                } catch (Exception e) {

                }
            }
        }
    }

    /**
     * 处理protobuf的序列化及返回结果
     * @param url
     * @param headerMap
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] post(String url, Map<String, String> headerMap, byte[] data) throws Exception {
        HttpPost httpPost = new HttpPost(url);// 创建httpPost
        //header
        for (String key : headerMap.keySet()) {
            httpPost.addHeader(key, headerMap.get(key));
        }
        ByteArrayEntity buf = new ByteArrayEntity(data);
        httpPost.setEntity(buf);
        //
        CloseableHttpResponse response = null;
        HttpEntity httpEntity = null;



        try {
            response = getHttpClient().execute(httpPost);
            httpEntity = response.getEntity();

            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            httpEntity.writeTo(buffer);
            return buffer.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;

        } finally {
            if (null != response) {
                try {
                    response.close();
                } catch (Exception e) {

                }
            }
        }
    }

    public static String execPost(String url,String value, String code) throws Exception {
        if (null == code) {
            code = "UTF-8";
        }
        HttpPost post = new HttpPost(url);

        post.setHeader("Content-type", "application/json; charset=" + code);
        post.setHeader("connection", "Keep-Alive");
        post.setHeader("Accept", "application/json");
        StringEntity entity = new StringEntity(value, Charset.forName(code));
        entity.setContentEncoding(code);
        // 发送Json格式的数据请求
        entity.setContentType("application/json");
        post.setEntity(entity);


        CloseableHttpResponse response = null;
        String rtn = "";
        BufferedReader reader = null;

        try {
            response = getHttpClient().execute(post);

            HttpEntity httpEntity = response.getEntity();
            InputStream in = httpEntity.getContent();
            reader = new BufferedReader(new InputStreamReader(in, code));
            StringBuffer sb = new StringBuffer();

            String line;
            while((line = reader.readLine()) != null) {
                sb.append(line);
            }
            rtn = sb.toString();
            in.close();
            return rtn;
        } catch (Exception var12) {
            throw var12;
        } finally {
            if (null != reader) {
                try {
                    reader.close();
                } catch (Exception e) {

                }
            }
            if (null != response) {
                try {
                    response.close();
                } catch (Exception e) {

                }
            }
        }
    }

    public static String execTextPost(String url,String value, String code) throws Exception {
        if (null == code) {
            code = "UTF-8";
        }
        HttpPost post = new HttpPost(url);

        post.setHeader("Content-type", "application/json; charset=" + code);
        post.setHeader("connection", "Keep-Alive");
        StringEntity entity = new StringEntity(value, Charset.forName(code));
        entity.setContentEncoding(code);
        // 发送Json格式的数据请求
        entity.setContentType("application/json");
        post.setEntity(entity);


        CloseableHttpResponse response = null;
        String rtn = "";
        BufferedReader reader = null;

        try {
            response = getHttpClient().execute(post);

            HttpEntity httpEntity = response.getEntity();
            InputStream in = httpEntity.getContent();
            reader = new BufferedReader(new InputStreamReader(in, code));
            StringBuffer sb = new StringBuffer();

            String line;
            while((line = reader.readLine()) != null) {
                sb.append(line);
            }
            rtn = sb.toString();
            in.close();
            return rtn;
        } catch (Exception var12) {
            throw var12;
        } finally {
            if (null != reader) {
                try {
                    reader.close();
                } catch (Exception e) {

                }
            }
            if (null != response) {
                try {
                    response.close();
                } catch (Exception e) {

                }
            }
        }
    }
}
